package commRedisService

import (
	"gitee.com/fierce_wolf/go-fox-edge-common/commEntity"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Differ"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Map"
	"sync"
)

type RedisAgileService struct {
	operator   RedisOperator
	mutex      sync.RWMutex     // 读写锁
	agileMap   map[string]int64 // 数据表的敏捷状态：轻量级数据
	updateTime int64            // redis的最近刷新时间
	needSave   bool             // 生产者：是否需要更新缓存到redis
	inited     bool             // 是否已经完成初始化
}

func (e *RedisAgileService) LoadAgileEntities() {
	// 读取时间戳
	syncTime, err := e.operator.readSync()
	if err != nil {
		return
	} else {
		e.updateTime = syncTime
	}

	// 读取敏捷数据：带有每个Entity的UpdateTime
	newUpdateTimes, err := e.operator.readAgileMap()
	if err != nil {
		return
	}
	if newUpdateTimes == nil {
		newUpdateTimes = make(map[string]int64)
	}

	// 多线程安全
	func() {
		e.mutex.Lock()
		defer e.mutex.Unlock()
		Map.Clear(e.agileMap)
		Map.Append(e.agileMap, newUpdateTimes)
	}()

}

func (e *RedisAgileService) LoadAllEntities() (map[string]commEntity.IEntity, error) {
	// 读取时间戳
	syncTime, err := e.operator.readSync()
	if err != nil {
		return nil, err
	} else {
		e.updateTime = syncTime
	}

	// 读取敏捷数据：带有每个Entity的UpdateTime
	newUpdateTimes, err := e.operator.readAgileMap()
	if err != nil {
		return nil, err
	}
	if newUpdateTimes == nil {
		newUpdateTimes = make(map[string]int64)
	}

	// 多线程安全
	func() {
		e.mutex.Lock()
		defer e.mutex.Unlock()
		Map.Clear(e.agileMap)
		Map.Append(e.agileMap, newUpdateTimes)
	}()

	// 读取data，并返回给外部
	return e.operator.ReadAllDataMap()
}

func (e *RedisAgileService) LoadChangeEntities(addMap *map[string]commEntity.IEntity, delMap *map[string]commEntity.IEntity, mdyMap *map[string]commEntity.IEntity) error {
	Map.Clear(*addMap)
	Map.Clear(*delMap)
	Map.Clear(*mdyMap)

	// 读取时间戳
	syncTime, err := e.operator.readSync()
	if err != nil {
		return err
	}

	// 检查：总时间戳是否发生了变化
	if e.updateTime == syncTime {
		return nil
	}

	// 记录下新的时间戳
	e.updateTime = syncTime

	// 读取敏捷数据：带有每个Entity的UpdateTime
	newUpdateTimes, err := e.operator.readAgileMap()
	if err != nil {
		return err
	}
	if newUpdateTimes == nil {
		newUpdateTimes = make(map[string]int64)
	}

	// 比较：key是否发生了变化
	addList := make(map[string]interface{})
	delList := make(map[string]interface{})
	eqlList := make(map[string]interface{})
	func() {
		// 多线程安全
		e.mutex.Lock()
		defer e.mutex.Unlock()
		Differ.Set.DifferByKey(e.agileMap, newUpdateTimes, &addList, &delList, &eqlList)
	}()

	// 比较：时间戳是否发生了变化
	mdfList := make(map[string]interface{})
	func() {
		// 多线程安全
		e.mutex.Lock()
		defer e.mutex.Unlock()

		for key := range eqlList {
			newUpdateTime := newUpdateTimes[key]
			oldUpdateTime := e.agileMap[key]
			if newUpdateTime == oldUpdateTime {
				continue
			}

			mdfList[key] = nil
		}
	}()

	if len(addList) == 0 && len(delList) == 0 && len(mdfList) == 0 {
		return nil
	}

	loads := make(map[string]interface{})
	Map.Append(loads, addList)
	Map.Append(loads, mdfList)

	// 读取全量的date：redis基础组件，没有读取指定数据的Map接口
	dataMap, err := e.operator.readEntityMap(Map.GetKeys(loads))
	if err != nil {
		return err
	}

	// 新增的数据
	// 多线程安全
	func() {
		e.mutex.Lock()
		defer e.mutex.Unlock()

		for key := range addList {
			data := dataMap[key]
			if data == nil {
				continue
			}

			newUpdateTime := newUpdateTimes[key]
			e.agileMap[key] = newUpdateTime

			(*addMap)[key] = data
		}
	}()

	// 修改的数据
	func() {
		e.mutex.Lock()
		defer e.mutex.Unlock()

		for key := range mdfList {
			data := dataMap[key]
			if data == nil {
				continue
			}

			newUpdateTime := newUpdateTimes[key]
			e.agileMap[key] = newUpdateTime

			(*mdyMap)[key] = data
		}
	}()

	// 删除的数据
	func() {
		e.mutex.Lock()
		defer e.mutex.Unlock()

		for key := range delList {
			_, ok := e.agileMap[key]
			if !ok {
				continue
			}

			(*delMap)[key] = nil
		}
	}()

	return nil
}
